package com.supermap.dataservice.rsm.service.impl;

import com.supermap.dataservice.rsm.entity.DataInfo;
import com.supermap.dataservice.rsm.entity.ProductInfo;
import com.supermap.dataservice.rsm.service.NetCdfService;
import com.supermap.dataservice.util.NetCDFAllUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import ucar.nc2.NetcdfFile;

import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.IOException;


/**
 * @author zhoujian
 * @version V1.0
 * @Description: Netcdf操作Service
 * @date 2018-1-8
 */
@Service
public class NetCdfServiceImpl implements NetCdfService {
    private Logger logger = LoggerFactory.getLogger(NetCdfServiceImpl.class);

    /**
     * @return DataInfo
     * @throws
     * @Description: 解析netcdf文件并封装成DataInfo对象返回
     * @author zhoujian
     */
    @Override
    public DataInfo getDataInfo(ProductInfo p) {
        DataInfo dataInfo = null;
        NetcdfFile netcdfFile = null;
        try {
            netcdfFile = NetcdfFile.open(p.getProductFilePath());
            float[][] datas = getNetcdfDataByPath(netcdfFile, p.getProductElement());
            Rectangle2D rectangle2d = getNetcdfRectangle2D(netcdfFile);
            Point2D point2d = getNetcdfResolution(netcdfFile);
            float left = (float) rectangle2d.getX();
            float right = (float) rectangle2d.getWidth();
            float bottom = (float) rectangle2d.getY();
            float top = (float) rectangle2d.getHeight();
            float dx = (float) point2d.getX();
            float dy = (float) point2d.getY();
            dataInfo = new DataInfo();
            dataInfo.setLeft(left);
            dataInfo.setRight(right);
            dataInfo.setBottom(bottom);
            dataInfo.setTop(top);
            dataInfo.setDx(dx);
            dataInfo.setDy(dy);
            dataInfo.setValues(datas);
            logger.info("获取netcdf文件[" + p.getProductFilePath() + "]成功。");
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("获取netcdf文件[" + p.getProductFilePath() + "]数据异常，异常信息：" + e);
        } finally {
            if (netcdfFile != null) {
                try {
                    netcdfFile.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    logger.error("关闭Netcdf文件对象异常 , 异常信息 ： " + e);
                }
            }
        }
        return dataInfo;
    }

    /**
     * 一维数组转化成二维数组
     *
     * @return float[][]
     * @throws
     * @Description: 一维数组转化成二维数组
     * @author zhoujian
     */
    private float[][] getNetcdfDataByPath(NetcdfFile ncFile, String element) {
        float[][] resultData = null;
        try {
            float[] values = NetCDFAllUtil.getValues(element, ncFile);
            int rows = NetCDFAllUtil.getRows(ncFile);
            int clos = NetCDFAllUtil.getCols(ncFile);
            resultData = new float[rows][clos];
            for (int i = 0; i < rows; i++) {
                for (int j = 0; j < clos; j++) {
                    resultData[i][j] = values[i * clos + j];
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("把数据从一维数组转换成二维数组异常,异常信息： " + e);
        }

        return resultData;
    }

    /**
     * 获取文件数据经纬度范围
     *
     * @return Rectangle2D
     * @throws
     * @Description: 获取文件数据经纬度范围
     * @author zhoujian
     */
    private Rectangle2D getNetcdfRectangle2D(NetcdfFile ncFile) throws Exception {
        Rectangle2D rectangle2d = NetCDFAllUtil.getGeoBounds(ncFile);
        return rectangle2d;
    }

    /**
     * 获取文件数据分辨率
     *
     * @return Point2D
     * @throws
     * @Description: 获取文件数据分辨率
     * @author zhoujian
     */
    private Point2D getNetcdfResolution(NetcdfFile ncFile) throws Exception {
        Point2D point2d = NetCDFAllUtil.getCellSize(ncFile);
        return point2d;
    }
}
